package com.k9sv.dao.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class PojoManager<T> extends HibernateDaoSupport {

	Logger log = Logger.getLogger(PojoManager.class);

	public int batchUpdate(String updateHql, Object[] values) throws Exception {
		Query q;
		try {
			q = getSession().createQuery(updateHql);
			if (values != null)
				for (int i = 0; i < values.length; ++i)
					q.setParameter(i, values[i]);
			return q.executeUpdate();
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			throw new Exception(e);
		}
	}

	public <T> void delete(T entity) throws Exception {
		try {
			getHibernateTemplate().delete(entity);
		} catch (Throwable e) {
			this.log.error(e.getMessage(), e);
			throw new Exception(e);
		}
	}

	public <T> void deletes(Collection<T> entities) throws Exception {
		try {
			if ((entities != null) && (entities.size() > 0))
				getHibernateTemplate().deleteAll(entities);
		} catch (Throwable e) {
			this.log.error(e.getMessage(), e);
			throw new Exception(e);
		}
	}

	public <T> T save(T entity) throws Exception {
		try {
			getHibernateTemplate().save(entity);
			return entity;
		} catch (Throwable e) {
			this.log.error(e.getMessage(), e);
			throw new Exception(e);
		}
	}

	public <T> void update(T entity) throws Exception {
		try {
			getHibernateTemplate().update(entity);
		} catch (Throwable e) {
			this.log.error(e.getMessage(), e);
			throw new Exception(e);
		}
	}

	public <T> void merge(T entity) throws Exception {
		try {
			getHibernateTemplate().merge(entity);
		} catch (Throwable e) {
			this.log.error(e.fillInStackTrace());
			throw new Exception(e);
		}
	}

	public <T> T getByClassId(Class<? extends T> clazz, Serializable id)
			throws Exception {
		try {
			return (T) getHibernateTemplate().get(clazz, id);
		} catch (Throwable e) {
			this.log.error(e.getMessage(), e);
			throw new Exception(e.getMessage(), e);
		}
	}

	public <T> List<T> query(String query, Object[] values, int start, int size)
			throws Exception {
		return this.query(query, values, start, size, true);
	}

	public <T> List<T> query(String query, Object[] values, int start,
			int size, boolean cacheable) throws Exception {
		Query q = null;
		List<T> _list = new ArrayList<T>();
		Session session = this.getSession();
		try {
			q = session.createQuery(query);
			q.setFirstResult(start);
			q.setMaxResults(size);
			q.setCacheable(cacheable);
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			throw new Exception(e);
		}
		if ((values != null) && (values.length > 0))
			for (int i = 0; i < values.length; ++i)
				q.setParameter(i, values[i]);
		_list = q.list();
		session.close();
		return _list;
	}

	public <T> List<T> querySQL(String query, Object[] values, int start,int size) throws Exception {
		return this.querySQL(query, values, start, size, false);
	}

	public <T> List<T> querySQL(String query, Object[] values, int start,
			int size, boolean cacheable) throws Exception {
		Query q = null;
		List<T> _list = new ArrayList<T>();
		Session session = this.getSession();
		try {
			q = session.createSQLQuery(query);
			q.setFirstResult(start);
			q.setMaxResults(size);
			q.setCacheable(cacheable);
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			throw new Exception(e);
		}
		if ((values != null) && (values.length > 0))
			for (int i = 0; i < values.length; ++i)
				q.setParameter(i, values[i]);
		_list = q.list();
		session.close();
		return _list;
	}

	public <T> List<T> querySorted(String query, String sortField,
			Object[] values, int start, int size) throws Exception {
		Query q = null;
		List<T> _list = new ArrayList<T>();
		Session session = this.getSession();
		try {
			query += " order by " + sortField;
			q = session.createQuery(query);
			q.setFirstResult(start);
			q.setMaxResults(size);
			q.setCacheable(true);
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			throw new Exception(e);
		}
		if ((values != null) && (values.length > 0))
			for (int i = 0; i < values.length; ++i)
				q.setParameter(i, values[i]);
		_list = q.list();
		session.close();
		return _list;
	}

	public Object getCount(String where, Object[] values) throws Exception {
		return this.getCount(where, values, true);
	}

	public Object getCount(String where, Object[] values, boolean CACHE)
			throws Exception {
		Session session = this.getSession();
		Object obj = new Object();
		try {
			Query query = session.createQuery(where);
			if (values != null) {
				int objectsize = values.length;
				if (objectsize > 0) {
					for (int i = 0; i < objectsize; i++) {
						query.setParameter(i, values[i]);
					}
				}
			}
			if (query == null) {
				return null;
			}
			obj = query.uniqueResult();
		} catch (Exception e) {
			obj = null;
			session.close();
			this.log.error(e.getMessage(), e);
			throw new Exception(e);
		}
		session.close();
		return obj;
	}

	public Object getCountSQL(String where, Object[] values) throws Exception {
		return this.getCountSQL(where, values, true);
	}

	public Object getCountSQL(String where, Object[] values, boolean CACHE)
			throws Exception {
		Session session = this.getSession();
		Object obj = new Object();
		try {
			Query query = session.createSQLQuery(where);
			if (values != null) {
				int objectsize = values.length;
				if (objectsize > 0) {
					for (int i = 0; i < objectsize; i++) {
						query.setParameter(i, values[i]);
					}
				}
			}
			if (query == null) {
				return null;
			}
			obj = query.uniqueResult();
		} catch (Exception e) {
			obj = null;
			session.close();
			this.log.error(e.getMessage(), e);
			throw new Exception(e);
		}
		session.close();
		return obj;
	}

	public <T> List<T> getAll(String query) throws Exception {
		Query q = null;
		List<T> _list = new ArrayList<T>();
		Session session = this.getSession();
		try {
			q = session.createQuery(query);
			q.setCacheable(true);
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			throw new Exception(e);
		}
		_list = q.list();
		session.close();
		return _list;
	}
	
	public <T> List<T> queryAll(String query,String sortField, Object[] values)
			throws Exception {
		return this.queryAll(query, values, sortField, true);
	}

	public <T> List<T> queryAll(String query, Object[] values,String sortField,  boolean cacheable) throws Exception {
		Query q = null;
		List<T> _list = new ArrayList<T>();
		Session session = this.getSession();
		try {
			q = session.createQuery(query);
			q.setCacheable(true);
			if(sortField!=null){
				query += " order by " + sortField;
			}
			q = session.createQuery(query);
			q.setCacheable(cacheable);
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			throw new Exception(e);
		}
		if ((values != null) && (values.length > 0))
			for (int i = 0; i < values.length; ++i)
				q.setParameter(i, values[i]);
		_list = q.list();
		session.close();
		return _list;
	}
}
